package bueu.bexl;


public class FunctionExpr extends BexlExpr {

	private final String name;
	private final BexlExpr firstParam;
	private final short totalParams;
	
	public FunctionExpr(final String name, final BexlExpr firstParam) {
		super(firstParam == null? false : firstParam.isRelative());
		this.name = name;
		this.firstParam = firstParam;
		
		BexlExpr next = firstParam;
		short i = 0;

		for (; next != null; i++) {
			next = next instanceof ParamExpr? ((ParamExpr) next).getNext() : null;
		}
		
		this.totalParams = i;
	}
	
	@Override
	protected final Object eval(final BexlCtx ctx, final Object current, final boolean set,
			final Object newValue) throws BexlException {
		Object[] params = new Object[this.totalParams];
		BexlExpr next = this.firstParam;
		
		for (int i = 0; next != null; i++) {
			params[i] = next.eval(ctx, current, set, newValue);
			next = next instanceof ParamExpr? ((ParamExpr) next).getNext() : null;
		}
		
		return ctx.invokeFunction(this.name, params);
	}
	
	@Override
	public final String toString() {
		StringBuilder sb = new StringBuilder(this.name).append("(");
		BexlExpr param = this.firstParam;
		
		while (param != null) {
			sb.append(param);
			
			if (param instanceof ParamExpr) {
				sb.append(", ");
				param = ((ParamExpr) param).getNext();
			} else {
				param = null;
			}
		}
		
		sb.append(")");

		return sb.toString();
	}
}
